package com.fary.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class SocketNIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ssc.socket().bind(new InetSocketAddress(9999));
        Selector selector = Selector.open();
        ssc.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 如果没有请求过来会在这里阻塞
            int n = selector.select();
            if (0 == n) {
                continue;
            }

            Iterator iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = (SelectionKey) iterator.next();

                // 如果处于accept状态，则可以连接了
                if (selectionKey.isAcceptable()) {
                    // 获取Socket连接的通道
                    SocketChannel socketChannel = ((ServerSocketChannel) selectionKey.channel()).accept();
                    System.out.println("request coming...");
                    socketChannel.configureBlocking(false);
                    // 建立连接后，就可以开始读socket发过来的消息了
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

                // 如果处于可读取数据状态-接受客户端数据
                else if (selectionKey.isReadable()) {
                    System.out.println("reading data...");
                    // 读数据
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    socketChannel.configureBlocking(false);
                    while (true) {
                        // 当客户端断开后才会返回-1，否则没有读到数据时返回0
                        int s = socketChannel.read(byteBuffer);
                        System.out.println("s=" + s);
                        if (s == 0 || s == -1) {
                            break;
                        }
                        byteBuffer.flip();
                        while (byteBuffer.hasRemaining()) {
                            System.out.print((char) byteBuffer.get());
                        }
                        System.out.println("\n--------");
                        byteBuffer.clear();
                    }
                    //socketChannel.close();

                    // 读完就给客户端回消息
                    socketChannel.register(selector, SelectionKey.OP_WRITE);

                }

                // 如果处于可以可写入数据状态--发送数据给客户端
                else if (selectionKey.isWritable()) {
                    System.out.println("writing data...");
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    socketChannel.configureBlocking(false);
                    ByteBuffer byteBuffer = ByteBuffer.wrap("I'm server, I send u some messages.".getBytes());
                    socketChannel.write(byteBuffer);
                    socketChannel.close();
                }

                // 删除已使用过的selectionKey
                iterator.remove();
            }
        }
    }
}